﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataSyn.MDL.DataBase
{
    class Sync
    {

        public System.Threading.ThreadState statu()
        {
            return thread.threadState;
        }
        public class Progress
        {
            /// <summary>
            /// 项目名称
            /// </summary>
            public string projectName { get; set; }
            /// <summary>
            /// 连接名
            /// </summary>
            private string _connName;
            public string connName
            {
                get
                {
                    return _connName;
                }
                set
                {
                    _connName = value;
                    tableName = null;
                }
            }
            private string _tableName;
            /// <summary>
            /// 数据表名
            /// </summary>
            public string tableName
            {
                get
                {
                    return _tableName;
                }
                set
                {
                    _tableName = value;
                }
            }
            private int _count_All;
            /// <summary>
            /// 总数据量
            /// </summary>
            public int count_All
            {
                get
                {
                    return _count_All;
                }
                set
                {
                    _count_All = value;
                    count = 0;
                    msg = null;
                }
            }
            /// <summary>
            /// 已处理数据量
            /// </summary>
            public int count { get; set; }
            /// <summary>
            /// 其它消息
            /// </summary>
            public string msg { get; set; }
        }
        ClassLibrary_Public.CThread thread = new ClassLibrary_Public.CThread();
        public Progress progress;
        /// <summary>
        /// 项目名
        /// </summary>
        public string projectName
        {
            get
            {
                return project.ProjectName;
            }
        }
        private static string syncSchema = "sync";
        private static string syncHead = "sync";
        private static string syncTriggerHead = "syncTgr";
        private static int pageSize = 10;
        CDataContext.DataContext dc_Master = null;
        MDL.ConfigSet.ProjectSection project;
        /// <summary>
        /// 所有的触发器
        /// </summary>
        List<CDataContext.CSource.CSYS_TRIGGER> List_Triggers = new List<CDataContext.CSource.CSYS_TRIGGER>();
        /// <summary>
        /// 同步表的同步结构
        /// </summary>
        CDataContext.CAttribute.DataTableattirbute syncTableSchema = new MDL.DataBase.SyncTableBase().getSchema() as CDataContext.CAttribute.DataTableattirbute;

        public Sync(MDL.ConfigSet.ProjectSection project)
        {
            syncTableSchema.Schema = syncSchema;
            this.project = project;
            var conn = this.project.GetMastConn();
            if (conn != null)
                dc_Master = new CDataContext.DataContext(conn.Provider, conn.Connection);
            dc_Master.log = new EAF.Log.Log(ClassLibrary_Public.CAppSetting.getAppDataPath(projectName), EAF.Log.LogType.Daily);
            foreach (var connelement in project.ConnCollection)
            {
                conn = new CDataContext.ConnectionSetting.Conn() { Provider_Str = connelement.Provider, Connection = connelement.ConnectionString };
            }
            progress = new Progress() { projectName = this.projectName };
        }
        /// <summary>
        /// 初始化主数据库同步功能
        /// </summary>
        public void CreateMaster()
        {
            bool isRun = ClassLibrary_Public.CConver.getBool(project.IsRunning);
            if (isRun)
                StopSync();
            if (dc_Master.getListBySql<int>("select count(*) from sys.schemas  where name={0}", syncSchema).FirstOrDefault() == 0)
            {
                dc_Master.runSql(string.Format("create schema {0}", syncSchema));
            }
            var tableList = dc_Master.getTables();
            var project_TableList = project.TableCollection.Select(c => c.TableName).ToList();
            List_Triggers = dc_Master.GetTrigger().Where(c => c.triggerName.IndexOf(syncTriggerHead) == 0).ToList();
            #region 删除不同步的触发器
            {
                foreach (var triger in List_Triggers)
                {
                    dc_Master.runSql(string.Format("drop trigger {0}", triger.triggerName));
                }
            }
            #endregion
            #region 删除不同步的sync结构表
            {
                foreach (var table in tableList.Where(c => c.schemaName == syncSchema && project_TableList.Select(d => syncHead + d.Split('.')[1]).Count(d => d == c.tableName) == 0))
                    dc_Master.runSql(string.Format("drop table {0}.{1}", table.schemaName, table.tableName));
            }
            #endregion
            #region 创建同步表及触发器
            {
                foreach (var table_tem in project_TableList)
                {
                    CreateTable(table_tem);
                }
            }
            #endregion
            if (isRun)
                StartSync();
        }
        public void CreateTable(string table_tem)
        {
            var tableName = table_tem.Split('.')[1];
            #region 同步表
            var syncTableSchema = (new MDL.DataBase.SyncTableBase()).getSchema() as CDataContext.CAttribute.DataTableattirbute;
            syncTableSchema.Schema = syncSchema;
            syncTableSchema.Att_Name = string.Format("{0}{1}", syncHead, tableName);
            var pkcolumn = syncTableSchema.ListColumns.Select(c => c as CDataContext.CAttribute.DataColumnAttirbute).FirstOrDefault(c => c.Att_ISPrimary);
            if (pkcolumn == null)
                pkcolumn.Att_PrimaryKeyName = pkcolumn.Att_DFName = string.Format("PF{0}{1}", syncSchema, tableName);
            else
                pkcolumn.Att_PrimaryKeyName = "PK_" + syncSchema + tableName;
            foreach (var columns_Schema in dc_Master.GetTableColumns(tableName))
            {
                syncTableSchema.ListColumns.Add(new CDataContext.CAttribute.DataColumnAttirbute()
                {
                    Att_Column = columns_Schema.columnName,
                    Att_DataSourceColumnName = columns_Schema.columnName,
                    Att_DataType = CDataContext.DataTypeCover.toDbType(ClassLibrary_Public.CEnum.getValue<System.Data.SqlDbType>(columns_Schema.columnDataType)),
                    Att_DataType_SqlServer = ClassLibrary_Public.CEnum.getValue<System.Data.SqlDbType>(columns_Schema.columnDataType),
                    Att_AlowNULL = columns_Schema.isNullAble,
                    Att_DataLength = columns_Schema.columnDataLength,
                    Att_DefaultValue = columns_Schema.defaultValue,
                    Extended_Property = columns_Schema.Extended_Property,
                });
            }
            dc_Master.CheckTable(new CDataContext.CAttribute.DataTableattirbute[] { syncTableSchema });
            #endregion
            #region 触发器
            var sql_Builder = new StringBuilder();
            if (List_Triggers.Count(c => c.triggerName == string.Format("{0}{1}", syncTriggerHead, tableName)) == 0)
            {
                sql_Builder.AppendLine(string.Format("create trigger {0}.{1}{2} on {0}.{2} for insert,update,delete as ", table_tem.Split('.')[0], syncTriggerHead, tableName));
            }
            else
            {
                sql_Builder.AppendLine(string.Format("alter trigger {0}.{1}{2} on {0}.{2} for insert,update,delete as ", table_tem.Split('.')[0], syncTriggerHead, tableName));
            }
            //判断是否删除
            sql_Builder.AppendLine("begin try");
            sql_Builder.AppendLine("if exists (select 1 from deleted) and  exists (select 1 from inserted)");
            sql_Builder.AppendLine("begin");
            sql_Builder.AppendLine(string.Format("insert into {0}.{1}({2}) select 'update',getdate(),{3} from inserted", syncSchema, syncTableSchema.Att_Name, string.Join(",", syncTableSchema.ListColumns.Skip(1).Select(c => c.Att_Column).ToArray()), string.Join(",", syncTableSchema.ListColumns.Skip(3).Select(c => c.Att_Column).ToArray())));
            sql_Builder.AppendLine("end");
            //判断是否删除
            sql_Builder.AppendLine("else if exists (select 1 from deleted)");
            sql_Builder.AppendLine("begin");
            sql_Builder.AppendLine(string.Format("insert into {0}.{1}({2}) select 'delete',getdate(),{3} from deleted", syncSchema, syncTableSchema.Att_Name, string.Join(",", syncTableSchema.ListColumns.Skip(1).Select(c => c.Att_Column).ToArray()), string.Join(",", syncTableSchema.ListColumns.Skip(3).Select(c => c.Att_Column).ToArray())));
            sql_Builder.AppendLine("end");
            //判断是否插入
            sql_Builder.AppendLine("else if exists (select 1 from inserted)");
            sql_Builder.AppendLine("begin");
            sql_Builder.AppendLine(string.Format("insert into {0}.{1}({2}) select 'insert',getdate(),{3} from inserted", syncSchema, syncTableSchema.Att_Name, string.Join(",", syncTableSchema.ListColumns.Skip(1).Select(c => c.Att_Column).ToArray()), string.Join(",", syncTableSchema.ListColumns.Skip(3).Select(c => c.Att_Column).ToArray())));
            sql_Builder.AppendLine("end");
            sql_Builder.AppendLine("end try");
            sql_Builder.AppendLine("begin catch");
            sql_Builder.AppendLine("end catch");
            dc_Master.runSql(sql_Builder.ToString());
            ///重新获取所有触发器
            List_Triggers = dc_Master.GetTrigger().Where(c => c.triggerName.IndexOf(syncTriggerHead) == 0).ToList();
            #endregion
        }
        /// <summary>
        /// 取消初始化主数据库同步功能
        /// </summary>
        public void CancelMaster()
        {
            var tableList = dc_Master.getTables();
            var project_TableList = project.TableCollection.Select(c => c.TableName).ToList();
            #region 删除同步的触发器
            {
                var triggers = dc_Master.GetTrigger().Where(c => c.triggerName.IndexOf(syncTriggerHead) == 0).ToList();
                foreach (var triger in triggers)
                {
                    dc_Master.runSql(string.Format("drop trigger {0}", triger.triggerName));
                }
            }
            #endregion
            #region 删除同步的sync结构表
            {
                foreach (var table in tableList.Where(c => c.schemaName == syncSchema))
                    dc_Master.runSql(string.Format("drop table {0}.{1}", table.schemaName, table.tableName));
            }
            #endregion
            ///删除同步架构
            if (dc_Master.getListBySql<int>("select count(*) from sys.schemas  where name={0}", syncSchema).FirstOrDefault() == 0)
            {
                dc_Master.runSql(string.Format("drop schema {0}", syncSchema));
            }
        }
        /// <summary>
        /// 创建客户端表结构
        /// </summary>
        /// <param name="connName"></param>
        public void CreateClientDataSchema(string connName = null)
        {
            if (!dc_Master.ConnTest) return;
            var list_Client = project.ConnCollection.ToArray();
            if (list_Client != null && !string.IsNullOrWhiteSpace(connName))
                list_Client = list_Client.Where(c => c.ConnName == connName).ToArray();
            foreach (var client in list_Client)
            {
                if (!client.dc.ConnTest) continue;
                foreach (var master_tableElement in project.TableCollection.ToArray())
                {
                    var client_TableElement = client.TableCollection.FirstOrDefault(c => c.TableName == master_tableElement.TableName);
                    if (client_TableElement == null)
                        client.TableCollection.Set(client_TableElement = new ConfigSet.TableElement() { TableName = master_tableElement.TableName, ClientTableName = master_tableElement.TableName });
                    if (string.IsNullOrWhiteSpace(client_TableElement.ClientTableName))
                        client_TableElement.ClientTableName = client_TableElement.TableName;
                    var master_tableColumns = dc_Master.GetTableColumns(master_tableElement.TableName);
                    if (master_tableColumns == null) continue;
                    var masterTableSchema = new CDataContext.CAttribute.DataTableattirbute() { Schema = client_TableElement.ClientTableName.Split('.')[0], Att_Name = client_TableElement.ClientTableName.Split('.')[1] };
                }
            }
        }
        /// <summary>
        /// 开始同步数据
        /// </summary>
        /// <param name="connName"></param>
        public void StartSync()
        {
            thread.start(() =>
            {
                dc_Master.CheckModule(new CDataContext.ModulePager());
                DateTime dt_MasterDataBaseResize = DateTime.Now;
                foreach (var conn in project.ConnCollection)
                    conn.dc.CheckModule(new CDataContext.CSqlModule());
                List_Triggers = null;
                while (true)
                {
                    try
                    {
                        List<CDataContext.CAttribute.DataTableattirbute> list_tableSchema = new List<CDataContext.CAttribute.DataTableattirbute>();
                        #region 检查同步表完整性
                        if (List_Triggers == null || List_Triggers.Count == 0)
                            List_Triggers = dc_Master.GetTrigger().Where(c => c.triggerName.IndexOf(syncTriggerHead) == 0).ToList();
                        progress.projectName = projectName;
                        progress.msg = "检测主连接要同步表完整性";
                        foreach (var masterTableElement in project.TableCollection)
                        {
                            CreateTable(masterTableElement.TableName);
                            //创建表
                            progress.tableName = masterTableElement.TableName;
                            //得到主表连接表结构
                            var tableSchema = new CDataContext.CAttribute.DataTableattirbute() { Schema = masterTableElement.TableName.Split('.')[0], Att_Name = masterTableElement.TableName.Split('.')[1] };
                            tableSchema.ListColumns.AddRange(dc_Master.GetTableColumnsAttribute(tableSchema.Att_Name, tableSchema.Schema).ToList());
                            list_tableSchema.Add(tableSchema);
                            //
                            foreach (var clientConnElement in project.ConnCollection.Where(c=>ClassLibrary_Public.CConver.getBool(  c.IsUsed)))
                            {
                                progress.connName = clientConnElement.ConnName;
                                progress.tableName = masterTableElement.TableName;
                                if (!clientConnElement.dc.ConnTest)
                                    continue;
                                clientConnElement.dc.log = dc_Master.log;
                                //检测客户端表结构
                                var clientTableElement = clientConnElement.TableCollection.FirstOrDefault(c => c.TableName == masterTableElement.TableName);
                                if (clientTableElement == null)
                                    clientConnElement.TableCollection.Set(clientTableElement = new ConfigSet.TableElement() { TableName = masterTableElement.TableName, ClientTableName = masterTableElement.TableName });
                                tableSchema.Schema = clientTableElement.TableName.Split('.')[0];
                                tableSchema.Att_Name = clientTableElement.TableName.Split('.')[1];
                                progress.msg = "查询表结构是否一致……";
                                clientConnElement.dc.CheckTable(tableSchema);
                                progress.msg = "查询表结构是否一致完成";
                                #region 从主表初始同步数据
                                //if (clientTableElement.LastUpdataDateTime == null)
                                {
                                    //检查与主库数据量一致性
                                    Sync_主表(tableSchema, clientConnElement, clientTableElement, masterTableElement);
                                }
                                #endregion
                            }
                        }
                        progress.msg = "检测主连接要同步表完整性完成";
                        #endregion
                        #region 开始同步数据
                        while (true)
                        {
                            try
                            {
                                foreach (var masterTableElement in project.TableCollection)
                                {
                                    var tableSchema = list_tableSchema.FirstOrDefault(c => c.Att_Name == masterTableElement.TableName.Split('.')[1]);

                                    progress.tableName = syncSchema + "." + syncHead + masterTableElement.TableName.Split('.')[1];
                                    CDataContext.PagerBack<Dictionary<string, object>> pager = new CDataContext.PagerBack<Dictionary<string, object>>();
                                    pager = dc_Master.Pager(progress.tableName, 1, pageSize, "", syncTableSchema.ListColumns.Select(c => c as CDataContext.CAttribute.DataColumnAttirbute).Where(c => c.Att_AutoIncrement).FirstOrDefault().Att_DataSourceColumnName);
                                    progress.count_All = pager.totalCount;

                                    if (pager.totalCount == 0)
                                    {
                                        progress.tableName = masterTableElement.TableName;
                                        progress.msg = "无同步数据，等待校验……";
                                        thread.sleep(1000);
                                        progress.msg = "无同步数据，开始校验……";
                                        foreach (var clientConnElement in project.ConnCollection.Where(c => ClassLibrary_Public.CConver.getBool(c.IsUsed)))
                                        {
                                            //检测客户端表结构
                                            var clientTableElement = clientConnElement.TableCollection.FirstOrDefault(c => c.TableName == masterTableElement.TableName);
                                            if (clientTableElement == null)
                                                clientConnElement.TableCollection.Set(clientTableElement = new ConfigSet.TableElement() { TableName = masterTableElement.TableName, ClientTableName = masterTableElement.TableName });
                                            Sync_主表(tableSchema, clientConnElement, clientTableElement, masterTableElement, true);
                                        }
                                    }
                                    else if (pager.totalCount > 0)
                                    {
                                        progress.msg = "从同步表中同步数据开始……";
                                        do
                                        {
                                            if (pager.totalCount == 0)
                                                break;
                                            Reader同步表(pager.rows.ToList(), tableSchema, syncTableSchema, masterTableElement);
                                            pager = dc_Master.Pager(progress.tableName, 1, pageSize, "", syncTableSchema.ListColumns.Select(c => c as CDataContext.CAttribute.DataColumnAttirbute).Where(c => c.Att_AutoIncrement).FirstOrDefault().Att_DataSourceColumnName);
                                        } while (pager.totalCount > 0);
                                        progress.msg = "从同步表中同步数据完成";
                                    }
                                }
                                //if (DateTime.Now.TimeOfDay.Hours < 3 && dt_MasterDataBaseResize.AddDays(1) < DateTime.Now)
                                //{
                                //    progress.msg = "正在收缩数据库";
                                //    dc_Master.resizeDataBase();
                                //    dt_MasterDataBaseResize = DateTime.Now;
                                //    progress.msg = "收缩数据库完成";
                                //}
                                progress.tableName = "";
                                dc_Master.Dispose();
                                thread.sleep(project.SleepMsec);
                            }
                            catch (Exception ex)
                            {
                                throw ex;
                            }

                        }
                        #endregion
                    }
                    catch (Exception ex)
                    {
                        dc_Master.log.Write("errmsg:"+ex.Message, EAF.Log.MsgType.Error);
                        dc_Master.Dispose();
                        thread.sleep(60000);
                        List_Triggers = new List<CDataContext.CSource.CSYS_TRIGGER>();
                    }
                }
            });
        }
        private void Sync_主表(CDataContext.CAttribute.DataTableattirbute tableSchema, ConfigSet.ConnElement clientConnElement, ConfigSet.TableElement clientTableElement, ConfigSet.TableElement masterTableElement, bool isReload = false)
        {
            if (string.IsNullOrWhiteSpace(clientTableElement.ClientTableName)) return;
            var masterCounts = dc_Master.getListBySql("select (select count(*) from " + masterTableElement.TableName + ") as masterCount,(select count(*) from " + syncSchema + "." + syncHead + masterTableElement.TableName.Split('.')[1] + ") as syncCount ").FirstOrDefault();
            var masterTableCount = ClassLibrary_Public.CConver.getInt(masterCounts["masterCount"]);
            var syncTablecount = ClassLibrary_Public.CConver.getInt(masterCounts["syncCount"]);
            if (isReload && syncTablecount != 0)
                return;
            var clientTableCount = clientConnElement.dc.getListBySql<int>(string.Format("select count(*) from {0}", clientTableElement.ClientTableName)).FirstOrDefault();

            if (clientTableCount < masterTableCount)//客户端表数据为空时从主连接的主表获取数据
            {
                if (isReload)
                    clientConnElement.dc.log.Write(string.Format("{0}连接中{1}数据检测不一致源表（{2})-目标表（{3}），重新同步！", clientConnElement.ConnName, clientTableElement.TableName,masterTableCount,clientTableCount), EAF.Log.MsgType.Error);
                progress.msg = "从主表中同步初始数据……";
                var column_auto = tableSchema.ListColumns.Cast<CDataContext.CAttribute.DataColumnAttirbute>().FirstOrDefault(c => c.Att_AutoIncrement);
                if (column_auto == null)
                {
                    var pager = dc_Master.Pager(masterTableElement.TableName, 1, pageSize);
                    progress.count_All = pager.totalCount;
                    while (pager.rows.Count > 0)
                    {
                        Reader主表(pager.rows.ToList(), clientConnElement, clientTableElement, tableSchema);
                        pager = dc_Master.Pager(masterTableElement.TableName, pager.pageIndex + 1, pageSize);
                    }
                }
                else
                {
                    var maxid = isReload ? 0 : clientConnElement.dc.getListBySql<int>("select max(" + column_auto.Att_Column + ") from " + clientTableElement.ClientTableName).FirstOrDefault();
                    if (maxid == 0)
                    {
                        var pager = dc_Master.Pager(masterTableElement.TableName, 1, pageSize, null, column_auto.Att_DataSourceColumnName);
                        progress.count_All = pager.totalCount;

                        while (pager.rows.Count > 0)
                        {
                            Reader主表(pager.rows.ToList(), clientConnElement, clientTableElement, tableSchema);
                            try
                            {
                                pager = dc_Master.Pager(masterTableElement.TableName, pager.pageIndex + 1, pageSize, null, column_auto.Att_DataSourceColumnName);
                            }
                            catch (Exception ex)
                            {
                                dc_Master.log.Write(ex.Message, EAF.Log.MsgType.Error);
                                thread.sleep(10000);
                            }
                        }
                    }
                    else
                    {
                        var pager = dc_Master.Pager(masterTableElement.TableName, 1, pageSize, column_auto.Att_Column + ">" + maxid.ToString(), column_auto.Att_DataSourceColumnName);
                        progress.count_All = pager.totalCount;
                        while (pager.rows.Count > 0)
                        {
                            Reader主表(pager.rows.ToList(), clientConnElement, clientTableElement, tableSchema);
                            try
                            {
                                pager = dc_Master.Pager(masterTableElement.TableName, pager.pageIndex + 1, pageSize, column_auto.Att_Column + ">" + maxid.ToString(), column_auto.Att_DataSourceColumnName);
                            }
                            catch (Exception ex)
                            {
                                dc_Master.log.Write(ex.Message, EAF.Log.MsgType.Error);
                                thread.sleep(10000);
                            }
                        }
                    }
                }
                progress.msg = "从主表中同步初始数据完成";
            }
        }
        /// <summary>
        /// 停止同步
        /// </summary>
        public void StopSync()
        {
            //thread.start(() =>
            {
                thread.close();
                //dc_Master.Dispose();
                //foreach (var c in project.ConnCollection.Where(c => c.dc != null))
                //    c.dc.Dispose();
            }
            //);
        }
        private void Reader同步表(List< Dictionary<string,object>> list_values , CDataContext.CAttribute.DataTableattirbute tableSchema, CDataContext.CAttribute.DataTableattirbute syncTableSchema, ConfigSet.TableElement masterTableElement)
        {
            List<Dictionary<string, object>> list_rows = new List<Dictionary<string, object>>();
            List<Dictionary<string, object>> List_SyncRows = new List<Dictionary<string, object>>();
            foreach (var row in list_values)
            {
                if (syncTableSchema != null)
                {
                    Dictionary<string, object> synccolumnsValue = new Dictionary<string, object>();

                    foreach (CDataContext.CAttribute.DataColumnAttirbute column in syncTableSchema.ListColumns)
                        synccolumnsValue.Add(column.Att_DataSourceColumnName, row[column.Att_Column]);
                    List_SyncRows.Add(synccolumnsValue);
                }
                Dictionary<string, object> columnsValue = new Dictionary<string, object>();
                foreach (CDataContext.CAttribute.DataColumnAttirbute column in tableSchema.ListColumns)
                    columnsValue.Add(column.Att_DataSourceColumnName, row[column.Att_Column]);
                list_rows.Add(columnsValue);
                progress.count++;
            }
            Writer(list_rows, tableSchema, syncTableSchema, List_SyncRows, masterTableElement);

        }
        private void Reader主表(List<Dictionary<string,object>> list_values, ConfigSet.ConnElement clientConnElement, ConfigSet.TableElement clientTableElement, CDataContext.CAttribute.DataTableattirbute tableSchema, CDataContext.CAttribute.DataTableattirbute syncTableSchema = null)
        {
            List<Dictionary<string, object>> list_rows = new List<Dictionary<string, object>>();
            List<Dictionary<string, object>> List_SyncRows = new List<Dictionary<string, object>>();
            foreach (var row in list_values)
            {
                if (syncTableSchema != null)
                {
                    Dictionary<string, object> synccolumnsValue = new Dictionary<string, object>();

                    foreach (CDataContext.CAttribute.DataColumnAttirbute column in syncTableSchema.ListColumns)
                        synccolumnsValue.Add(column.Att_DataSourceColumnName, row[column.Att_Column]);
                    List_SyncRows.Add(synccolumnsValue);
                }
                Dictionary<string, object> columnsValue = new Dictionary<string, object>();
                foreach (CDataContext.CAttribute.DataColumnAttirbute column in tableSchema.ListColumns)
                    columnsValue.Add(column.Att_DataSourceColumnName, row[column.Att_Column]);
                list_rows.Add(columnsValue);
                progress.count++;
            }
            Writer(list_rows, clientConnElement, clientTableElement, tableSchema, syncTableSchema == null ? null : syncTableSchema, syncTableSchema == null ? null : List_SyncRows);
        }
        private void Writer(List<Dictionary<string, object>> list_rows, ConfigSet.ConnElement clientConnElement, ConfigSet.TableElement clientTableElement, CDataContext.CAttribute.DataTableattirbute tableSchema, CDataContext.CAttribute.DataTableattirbute syncTableSchema = null, List<Dictionary<string, object>> list_SyncRows = null)
        {
            progress.msg = "客户端正保存……";
            var columnAuto = tableSchema.ListColumns.Cast<CDataContext.CAttribute.DataColumnAttirbute>().FirstOrDefault(c => c.Att_AutoIncrement);
            if (columnAuto != null)
                clientConnElement.dc.runSql("SET IDENTITY_INSERT " + clientTableElement.ClientTableName + " OFF;");
            using (var tra = clientConnElement.dc.CreateTransaction())
            {
                if (columnAuto != null)
                {
                    tra.CreateRunCommandCreateCommand("SET IDENTITY_INSERT " + clientTableElement.ClientTableName + " ON;");
                }
                #region 数据同步
                for (int irow = 0; irow < list_rows.Count; irow++)
                {
                    StringBuilder sb_sql = new StringBuilder();

                    var row = list_rows[irow];

                    List<System.Data.IDbDataParameter> list_values = new List<System.Data.IDbDataParameter>();
                    foreach (KeyValuePair<string, object> column_Value in row)
                    {
                        var col = tableSchema.ListColumns.Select(c => c as CDataContext.CAttribute.DataColumnAttirbute).FirstOrDefault(c => c.Att_DataSourceColumnName == column_Value.Key);
                        list_values.Add(clientConnElement.dc.getParameter(list_values.Count, column_Value.Value, col));
                    }
                    if (list_SyncRows != null && list_SyncRows.Count > 0)
                    {
                        if (string.Format("{0}", list_SyncRows[irow]["DataSyncType"]).ToLower() == "delete")
                        {
                            if (columnAuto == null)
                            {
                                sb_sql.AppendLine("delete from "
                                  + clientTableElement.ClientTableName
                                  + " where " + string.Join(" and ", list_values.Select(c => string.Format("{0}={1}", c.SourceColumn, c.ParameterName)).ToArray()));
                                tra.CreateRunCommandCreateCommand(sb_sql.ToString(), list_values.ToArray());
                            }
                            else
                            {
                                sb_sql.AppendLine("delete from "
                                   + clientTableElement.ClientTableName
                                   + " where " + list_values.Where(c => c.SourceColumn == columnAuto.Att_DataSourceColumnName).Select(c => string.Format("{0}={1};", c.SourceColumn, c.ParameterName)).FirstOrDefault());
                                tra.CreateRunCommandCreateCommand(sb_sql.ToString(), list_values.Where(c => c.SourceColumn == columnAuto.Att_DataSourceColumnName).ToArray());
                            }
                            continue;
                        }
                    }
                    if (columnAuto == null)
                    {
                        sb_sql.AppendLine("if((select count(*) from " + clientTableElement.ClientTableName + " where " + string.Join(" and ", list_values.Select(c => string.Format("{0}={1}", c.SourceColumn, c.ParameterName)).ToArray()) + ")=0)");
                        sb_sql.AppendLine("Begin");
                        sb_sql.AppendLine("insert into " + clientTableElement.ClientTableName + " (" + string.Join(",", list_values.Select(c => c.SourceColumn).ToArray()) + ") values(" + string.Join(",", list_values.Select(c => c.ParameterName).ToArray()) + ");");
                        sb_sql.AppendLine("End");
                    }
                    else
                    {
                        sb_sql.AppendLine("if((select count(*) from " + clientTableElement.ClientTableName + " where " + list_values.Where(c => c.SourceColumn == columnAuto.Att_DataSourceColumnName).Select(c => string.Format("{0}={1}", c.SourceColumn, c.ParameterName)).FirstOrDefault() + ")=0)");
                        sb_sql.AppendLine("Begin");
                        sb_sql.AppendLine("insert into " + clientTableElement.ClientTableName + " (" + string.Join(",", list_values.Select(c => c.SourceColumn).ToArray()) + ") values(" + string.Join(",", list_values.Select(c => c.ParameterName).ToArray()) + ");");
                        sb_sql.AppendLine("End");
                        sb_sql.AppendLine("Else");
                        sb_sql.AppendLine("Begin");
                        sb_sql.AppendLine("update " + clientTableElement.ClientTableName + " set " + string.Join(",", list_values.Where(c => c.SourceColumn != columnAuto.Att_DataSourceColumnName).Select(c => string.Format("{0}={1}", c.SourceColumn, c.ParameterName)).ToArray()) + " where " + string.Join(",", list_values.Where(c => c.SourceColumn == columnAuto.Att_DataSourceColumnName).Select(c => string.Format("{0}={1}", c.SourceColumn, c.ParameterName)).ToArray()) + ";");
                        sb_sql.AppendLine("End");
                    }
                    tra.CreateRunCommandCreateCommand(sb_sql.ToString(), list_values.ToArray());
                }

                #endregion
                if (columnAuto != null)
                    tra.CreateRunCommandCreateCommand("SET IDENTITY_INSERT " + clientTableElement.ClientTableName + " OFF;");
                tra.Commit();

            }
            progress.msg = "客户端正完成……";
        }
        private void Writer(List<Dictionary<string, object>> list_rows, CDataContext.CAttribute.DataTableattirbute tableSchema, CDataContext.CAttribute.DataTableattirbute syncTableSchema, List<Dictionary<string, object>> list_SyncRows, ConfigSet.TableElement masterTableElement)
        {
            foreach (var clientConnElement in project.ConnCollection.Where(c=>ClassLibrary_Public.CConver.getBool(c.IsUsed)))
            {
                progress.connName = clientConnElement.ConnName;
                progress.tableName = syncTableSchema == null ? masterTableElement.TableName : (syncSchema + "." + syncHead + masterTableElement.TableName.Split('.')[1]);
                var clientTableElement = clientConnElement.TableCollection.FirstOrDefault(c => c.TableName == masterTableElement.TableName);
                if (clientTableElement == null)
                    clientConnElement.TableCollection.Set(clientTableElement = new ConfigSet.TableElement() { TableName = masterTableElement.TableName, ClientTableName = masterTableElement.TableName });
                tableSchema.Schema = clientTableElement.TableName.Split('.')[0];
                tableSchema.Att_Name = clientTableElement.TableName.Split('.')[1];
                progress.msg = "查询表结构是否一致……";
                clientConnElement.dc.CheckTable(tableSchema);
                progress.msg = "查询表结构是否一致完成";
                progress.msg = "正在从同步表获取数据……";
                Writer(list_rows, clientConnElement, clientTableElement, tableSchema, syncTableSchema, list_SyncRows);
            }
            list_rows.Clear();
            if (syncTableSchema != null && list_SyncRows != null)
            {
                foreach (var row in list_SyncRows)
                    dc_Master.runSql("delete from " + syncSchema + "." + syncHead + tableSchema.Att_Name + " where DataSyncID={0}", (long)row["DataSyncID"]);
            }
        }
    }
}
 